/** @format */

import XLSX from 'xlsx'
import fs from 'fs-extra'
import { join, resolve, dirname } from 'path'

const globalConfig = {
  value: {},
}
export async function applyXlsx(config) {
  console.log('开始应用xlsx文件...')

  const {
    i18nDir,
    xlsxDir,
    searchLanguage,
    xlsxFileName = 'i18n_translations.xlsx',
    exportMode = 'single', // 与generator.js保持一致的模式配置
    isFile = false, // 是否为单一文件模式
    keyMode = 'obj', // key模式
  } = config

  // 全局配置
  globalConfig.flatKey = keyMode === 'flat'

  // 处理 languages 配置，删除其中与 searchLanguage 相同的项然后将 searchLanguage 放在首位
  let languages = config.languages || []
  const uniqueLanguages = Array.from(new Set(languages))
  languages = uniqueLanguages.filter((lang) => lang !== searchLanguage)
  languages.unshift(searchLanguage)

  // 确保i18n目录存在
  await fs.ensureDir(i18nDir)

  if (isFile) {
    // 单一文件模式 - 读取指定的XLSX文件
    await applyFromFile(xlsxDir, xlsxFileName, i18nDir, languages, true)
  } else {
    if (exportMode === 'single') {
      // 单文件模式 - 读取一个包含多个工作表的XLSX文件
      await applySingleFile(xlsxDir, xlsxFileName, i18nDir, languages)
    } else {
      // 多文件模式 - 读取多个XLSX文件
      await applyMultipleFiles(xlsxDir, i18nDir, languages)
    }
  }

  console.log('i18n配置文件更新完成!')
}

async function applySingleFile(xlsxDir, xlsxFileName, i18nDir, languages) {
  // 查找指定的xlsx文件
  const xlsxFilePath = join(xlsxDir, xlsxFileName)
  if (!(await fs.pathExists(xlsxFilePath))) {
    throw new Error(`xlsx文件不存在: ${xlsxFilePath}`)
  }

  console.log(`处理文件: ${xlsxFilePath}`)

  // 读取xlsx文件
  const workbook = XLSX.readFile(xlsxFilePath)

  // 处理每个工作表
  for (const sheetName of workbook.SheetNames) {
    console.log(`处理工作表: ${sheetName}`)

    const worksheet = workbook.Sheets[sheetName]
    const data = XLSX.utils.sheet_to_json(worksheet)

    // 从工作表名称还原模块文件路径
    const moduleFile = sheetName.replace(/_/g, '/') + '.js'

    // 为每种语言生成配置文件
    for (const lang of languages) {
      await updateLanguageFile(data, lang, i18nDir, moduleFile)
    }
  }
}

async function applyMultipleFiles(xlsxDir, i18nDir, languages) {
  // 获取所有xlsx文件
  const xlsxFiles = await getXlsxFiles(xlsxDir)

  // 处理每个xlsx文件
  for (const xlsxFile of xlsxFiles) {
    if (!xlsxFile.endsWith('.xlsx')) continue

    console.log(`处理文件: ${xlsxFile}`)

    // 读取xlsx文件
    const xlsxFilePath = join(xlsxDir, xlsxFile)
    const workbook = XLSX.readFile(xlsxFilePath)

    // 假设每个文件只有一个工作表，名称为'i18n'
    const sheetName = workbook.SheetNames[0]
    if (!sheetName) {
      console.warn(`文件 ${xlsxFile} 中没有工作表`)
      continue
    }

    const worksheet = workbook.Sheets[sheetName]
    const data = XLSX.utils.sheet_to_json(worksheet)

    // 从文件名还原模块文件路径（将下划线替换为路径分隔符）
    const moduleFile = xlsxFile.replace('.xlsx', '.js').replace(/_/g, '/')

    // 为每种语言生成配置文件
    for (const lang of languages) {
      await updateLanguageFile(data, lang, i18nDir, moduleFile)
    }
  }
}

async function applyFromFile(
  xlsxDir,
  xlsxFileName,
  i18nDir,
  languages,
  isFile = false
) {
  // 查找指定的xlsx文件
  const xlsxFilePath = join(xlsxDir, xlsxFileName)
  if (!(await fs.pathExists(xlsxFilePath))) {
    throw new Error(`xlsx文件不存在: ${xlsxFilePath}`)
  }

  console.log(`处理文件: ${xlsxFilePath}`)

  // 读取xlsx文件
  const workbook = XLSX.readFile(xlsxFilePath)

  // 处理每个工作表
  for (const sheetName of workbook.SheetNames) {
    console.log(`处理工作表: ${sheetName}`)

    const worksheet = workbook.Sheets[sheetName]
    const data = XLSX.utils.sheet_to_json(worksheet)

    let searchLanguageData = {}
    // 为每种语言生成配置文件
    for (const lang of languages) {
      await updateLanguageFile(
        data,
        lang,
        i18nDir,
        sheetName + '.js',
        isFile,
        searchLanguageData
      )
    }
  }
}

async function getXlsxFiles(xlsxDir) {
  if (!(await fs.pathExists(xlsxDir))) {
    throw new Error(`xlsx目录不存在: ${xlsxDir}`)
  }

  const files = await fs.readdir(xlsxDir)
  return files.filter((file) => file.endsWith('.xlsx'))
}

async function updateLanguageFile(
  data,
  lang,
  i18nDir,
  moduleFile,
  isFile,
  searchLanguageData
) {
  const langPath = join(i18nDir, lang)

  // 检查语言路径是文件还是目录
  let outputPath
  if (isFile) {
    outputPath = langPath + '.js'
    await fs.ensureDir(dirname(outputPath))
  } else {
    // 如果路径不存在，默认当作目录处理
    outputPath = join(langPath, moduleFile)
    await fs.ensureDir(dirname(outputPath))
  }

  const langData = {}
  const langKey = lang // xlsx中的列名应该与语言代码一致

  // 检查是否有该语言的列
  const hasLangColumn = data.length > 0 && langKey in data[0]
  if (!hasLangColumn) {
    console.warn(`xlsx文件中未找到语言列: ${langKey}`)
    return
  }

  // 构建语言对象
  for (const row of data) {
    if (row.key && row[langKey]) {
      setNestedValue(
        langData,
        row.key,
        row[langKey],
        searchLanguageData.value,
        lang
      )
    }
  }

  if (!searchLanguageData.value) {
    searchLanguageData.value = langData
  }

  // 拍平 langData
  const flattenedData = globalConfig.flatKey
    ? flattenObject(langData)
    : langData

  // 写入文件
  const fileContent = `export default ${JSON.stringify(
    flattenedData,
    null,
    2
  )};`
  await fs.writeFile(outputPath, fileContent)

  console.log(`更新文件: ${outputPath}`)
}

// 拍平一个对象
function flattenObject(obj) {
  const flattened = {}

  function flatten(obj, prefix = '') {
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const value = obj[key]
        const newKey = prefix ? `${prefix}.${key}` : key

        if (typeof value === 'object' && value !== null) {
          flatten(value, newKey)
        } else {
          flattened[newKey] = value
        }
      }
    }
  }
  flatten(obj)
  return flattened
}

function setNestedValue(obj, keyPath, value, searchLanguageData, lang) {
  if (keyPath[keyPath.length - 1] === '.') {
    const oldPath = keyPath
    keyPath = keyPath.slice(0, -1) + '_'
    if (!searchLanguageData) console.log('===> 发现末尾的点:', oldPath, ' \t替换为:', keyPath)
  }

  const keys = keyPath.split('.')
  let current = obj

  let search = searchLanguageData

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i]
    if (!(key in current) || typeof current[key] !== 'object') {
      current[key] = {}
    }
    current = current[key]

    if (search) {
      search = search[key]
    }
  }

  const lastKey = keys[keys.length - 1]
  if (search && search[lastKey]) {
    if(typeof search[lastKey] === 'object') {
      // 有异常
      console.warn('===> 多层级key不规范，当前key已被覆盖', keyPath)
    } else {
      const p = /\[[^\[\]]+\]/g
      // 正则匹配出所有的占位符
      const matches = search[lastKey].match(p)
      if (matches) {
        const valueMaches = value.match(p)
        if (!valueMaches) {
          console.warn('===> 翻译文本中缺少占位符:', keyPath, lang)
        } else {
          // console.log('发现占位符:',keyPath, matches, valueMaches)
          valueMaches.forEach((m, idx) => {
            value = value.replace(m, matches[idx])
          })
        }
      }
    }
  }

  current[lastKey] = value
}
